package bestTeam.WalkieDoggie.client.Composites;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.omg.CORBA.UserException;

import sun.net.www.content.audio.wav;

import bestTeam.WalkieDoggie.client.WalkieDoggie;
import bestTeam.WalkieDoggie.client.dateComperator;
import bestTeam.WalkieDoggie.client.walkieStatus;
import bestTeam.WalkieDoggie.client.Serializables.FBFriend;
import bestTeam.WalkieDoggie.client.Serializables.UserProfileData;
import bestTeam.WalkieDoggie.client.Serializables.UserRequest;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.StackPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class MyWalkiesComp extends Composite {

	//	ArrayList<UserRequest> myRequests = new ArrayList<UserRequest>();

	public ArrayList<UserRequest> requests = new ArrayList<UserRequest>();

	private Label title;
	private StackPanel stackMyWalkiesList;
	private VerticalPanel ver;

	private Label emptyLabel;

	private dateComperator date_comperator_asc=new dateComperator(1);

	protected userProfileComp userComp;
	protected mutualFriendsPopup mutualFriendsComp;
	private HashMap<String, List<FBFriend>> friendsOfFriendsMap;

	public MyWalkiesComp(HashMap<UserRequest,UserProfileData> requestsMap){

		ver = new VerticalPanel();
		
		title = new Label("My Walkies: ");
		title.setStyleName("titleForView");
		
		Label exp = new Label("\t shows your own future Walkies");
		
		HorizontalPanel hor = new HorizontalPanel();
		hor.add(title);
		
		hor.add(exp);
		hor.setCellVerticalAlignment(exp, HasVerticalAlignment.ALIGN_BOTTOM);
		
		ver.add(hor);
		
		ver.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		ver.setSpacing(5);
		initWidget(ver);
		ver.setSize("100%", "100%");

		stackMyWalkiesList = new StackPanel();
		//ver.add(title);
		ver.setCellWidth(title, "100%");
		ver.setCellHeight(title, "15px");
		ver.setCellHorizontalAlignment(title, HasHorizontalAlignment.ALIGN_LEFT);
		ver.add(stackMyWalkiesList);
		stackMyWalkiesList.setSize("100%", "100%");

		if(!WalkieDoggie.loginInfo.isNewUser())
			loadMyWalkies();

		emptyLabel = new Label("");
		ver.add(emptyLabel);
	}

	private ArrayList<UserRequest> getMyRequests(UserRequest[] requestsArray) {
		ArrayList<UserRequest> res = new ArrayList<UserRequest>();

		for (UserRequest userRequest : requestsArray) {

			if(userRequest.getDate().after(new Date()) &&
					userRequest.getCreatedBy().equals(WalkieDoggie.loginInfo.getUserData().getId()))
				res.add(userRequest);
		}

		return res;
	}

	public void loadMyWalkies() {

		if(WalkieDoggie.requestsOwnersMap!=null){
			UserRequest[] tmp = (UserRequest[])WalkieDoggie.requestsOwnersMap.keySet().toArray(new UserRequest[0]);
			requests = getMyRequests(tmp);
		}

		displayMyWalkies(requests);

	}

	private void displayMyWalkies(ArrayList<UserRequest> requests) {

		stackMyWalkiesList.clear();
		//myRequests.clear();

		UserRequest[] sorted = (UserRequest[])requests.toArray(new UserRequest[0]); 
		Arrays.sort(sorted,date_comperator_asc);
		for (UserRequest request: sorted) {

			if(request.getCreatedBy().equals(WalkieDoggie.loginInfo.getUserData().getId()))
				displayMyWalkie(request);
		}		
	}

	private void displayMyWalkie(final UserRequest request) {
		//myRequests.add(request);

		VerticalPanel myRequestPanel = new VerticalPanel();

		// Add a button to remove this request from the table.
		Button removeRequestButton = new Button("Cancel request");

		removeRequestButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				removeRequest(request);
				
			}

		});
		myRequestPanel.add(removeRequestButton);

		//Add a table of volunteers
		FlexTable fxTableVolunteers = new FlexTable();
		loadVolunteersTable(fxTableVolunteers,request);
		myRequestPanel.add(fxTableVolunteers);

		//DateTimeFormat fmt = DateTimeFormat.getFormat("EEEE, MMMM dd, yyyy");

		String msg = WalkieDoggie.fmt.format(request.getDate())+"\t"+request.getTimeFrame();

		stackMyWalkiesList.add(myRequestPanel, msg);
	}

	private void removeRequest(final UserRequest request) {
		WalkieDoggie.requestService.removeRequest(request.getId(), new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				requests.remove(request);
				WalkieDoggie.requestsOwnersMap.remove(request);
				displayMyWalkies(requests);
				WalkieDoggie.updateCounters();
				WalkieDoggie.create_walkies_comp.increaseCredit();
				WalkieDoggie.header.clear();
				WalkieDoggie.header.add(WalkieDoggie.header_comp);
			}

			@Override
			public void onFailure(Throwable caught) {
				WalkieDoggie.handleError(caught);

			}
		});

	}

	//	private void unDisplayRequest(UserRequest request) {
	//		int removedIndex = myRequests.indexOf(request);
	//		myRequests.remove(removedIndex);
	//		stackMyWalkiesList.remove(removedIndex);	
	//
	//		if(myRequests.size()==0)
	//			emptyLabel.setText("no items to show");
	//	}

	private void loadVolunteersTable(final FlexTable fxTableVolunteers, final UserRequest request) {
		
		friendsOfFriendsMap = new HashMap<String, List<FBFriend>>();
		
		String[] volunteers = request.getVolunteers();

		if(volunteers == null || volunteers.length == 0){
			fxTableVolunteers.setText(0, 0, ":(		Sorry, still no volunteers");

			//fxTableVolunteers.setText(1, 0, "Name");
			//fxTableVolunteers.setText(1, 1, "is FB friend?");
			//fxTableVolunteers.  setText(1, 2, "Status");

			return;
		}

		WalkieDoggie.usersService.getUsers(volunteers, new AsyncCallback<UserProfileData[]>() {

			@Override
			public void onFailure(Throwable caught) {
				WalkieDoggie.handleError(caught);
			}

			@Override
			public void onSuccess(UserProfileData[] volunteers) {

				fillVolunteersTable(volunteers,fxTableVolunteers, request);
			}


		});



	}

	private void fillVolunteersTable(UserProfileData[] volunteers, final FlexTable fxTableVolunteers, final UserRequest request) {
		fxTableVolunteers.setText(0, 0, ":)		There are some good people in this town!");

		fxTableVolunteers.setText(1, 0, "Name");
		fxTableVolunteers.setText(1, 1, "is FB friend?");
		fxTableVolunteers.setText(1, 2, "Status");
		fxTableVolunteers.setWidth("100%");

		HashMap<String, FBFriend> myFriends = WalkieDoggie.loginInfo.getUserData().getFB_Friends();
	
		for (final UserProfileData volunteer : volunteers) {
			final int row = fxTableVolunteers.getRowCount();
			fxTableVolunteers.setWidget(row, 0, new Anchor(volunteer.getNickName()));

			((Anchor)fxTableVolunteers.getWidget(row, 0)).addClickHandler(new ClickHandler() {


				@Override
				public void onClick(ClickEvent event) {

					userComp = new userProfileComp(volunteer,false);
					userComp.setPopupPosition(WalkieDoggie.header_comp.getAbsoluteLeft()+300, WalkieDoggie.header_comp.getAbsoluteTop()+200);
					userComp.setGlassEnabled(true);
					userComp.show();
				}
			});

			fxTableVolunteers.getRowFormatter().addStyleName(row, "volunteersTableSafeVolunteer");
			//fxTableVolunteers.getRowFormatter().addStyleName(row+1, "volunteersTableSafeVolunteer");
			fxTableVolunteers.getCellFormatter().addStyleName(row, 1, "isFBFriendCell");
			//fxTableVolunteers.getRowFormatter().addStyleName(row+1, "bottomBorder");

			boolean isFacebookFriend = false;
			boolean isFacebookFriendOfFriend = false;
			//List<FBFriend> friendsOfFriends = null;
			//if(the volunteer is a facebook friend of current user then it will appear as green. else, as something else.
			if(myFriends.containsKey(volunteer.getId())){				
				isFacebookFriend  = true;
			}
			else
			{
				//fxTableVolunteers.getRowFormatter().addStyleName(row, "volunteersTableUnSafeVolunteer");
				isFacebookFriend  = false;
				HashMap<String, FBFriend> volunteerFriends = volunteer.getFB_Friends();
				List<FBFriend> friendsOfFriends = getCommonFriends (volunteerFriends, myFriends);
				friendsOfFriendsMap.put(volunteer.getId(), friendsOfFriends);
				if (friendsOfFriends.size()>0){
					isFacebookFriendOfFriend = true;
				}
			}

			fxTableVolunteers.setText(row, 2, "Waiting for approval");	
			Image isFriendImage;
			if (isFacebookFriend) {
				isFriendImage = new Image("friend.png");
				isFriendImage.setSize("", "25px");
			} else {
				if (isFacebookFriendOfFriend) {
					isFriendImage = new Image("Facebook-Friends.jpg");
					isFriendImage.setSize("25px", "25px");
				} else {
					isFriendImage = new Image("Facebook-Friend-Not.jpg");
					isFriendImage.setSize("25px", "25px");
				}
			}
			
			VerticalPanel fbFriendPanel = new VerticalPanel();
			fbFriendPanel.add(isFriendImage);
			if (isFacebookFriendOfFriend){
				
				Anchor volunteerAnchor = new Anchor(friendsOfFriendsMap.get(volunteer.getId()).size() + "mutual friends");
				volunteerAnchor.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						// new popup thing with common friends
					}
				});
				fbFriendPanel.add(volunteerAnchor);
				((Anchor)fbFriendPanel.getWidget(1)).addClickHandler(new ClickHandler() {


					@Override
					public void onClick(ClickEvent event) {

						mutualFriendsComp = new mutualFriendsPopup(friendsOfFriendsMap.get(volunteer.getId()));
						mutualFriendsComp.setPopupPosition(WalkieDoggie.header_comp.getAbsoluteLeft()+300, WalkieDoggie.header_comp.getAbsoluteTop()+200);
						mutualFriendsComp.setGlassEnabled(true);
						mutualFriendsComp.show();
					}
				});
						}
			
			fxTableVolunteers.setWidget(row, 1, fbFriendPanel);
			//fxTableVolunteers.setWidget(row, 1,isFriendImage );
			fxTableVolunteers.setCellPadding(5);
			fxTableVolunteers.setCellSpacing(3);
			
			if(request.getApprovedWalkerID()==null ){
				fxTableVolunteers.setText(row, 2, "Waiting for approval");
				Button btnApproveVolunteer = new Button("approve volunteer");
				btnApproveVolunteer.addClickHandler(new ClickHandler() {

					@Override
					public void onClick(ClickEvent event) {

						approveVolunteer(volunteer.getId(),request,fxTableVolunteers,row);

					}

				});

				fxTableVolunteers.setWidget(row, 3, btnApproveVolunteer);
			}
			else{
				if(volunteer.getId().equals(request.getApprovedWalkerID())){
					fxTableVolunteers.setText(row, 2, "Approved!");
					Button btnDontApproveVolunteer = new Button("I dont want this walker");
					btnDontApproveVolunteer.addClickHandler(new ClickHandler() {

						@Override
						public void onClick(ClickEvent event) {

							dontApproveVolunteer(volunteer.getId(),request,fxTableVolunteers,row);

						}


					});

					//btnDontApproveVolunteer.setEnabled(false);
					fxTableVolunteers.setWidget(row, 3, btnDontApproveVolunteer);
				}

				else{
					fxTableVolunteers.setText(row, 2, "Waiting for approval");
					Button btnApproveVolunteer = new Button("approve volunteer");
					btnApproveVolunteer.addClickHandler(new ClickHandler() {

						@Override
						public void onClick(ClickEvent event) {

							approveVolunteer(volunteer.getId(),request,fxTableVolunteers,row);

						}

					});

					fxTableVolunteers.setWidget(row,3, btnApproveVolunteer);


				}
			}
		}

	}

	private List<FBFriend> getCommonFriends(HashMap<String, FBFriend> volunteerFriends, HashMap<String, FBFriend> myFriends) {

		Set<String> friendIDs = myFriends.keySet();
		
		ArrayList<String> friendIdsClone = new ArrayList<String>();
		for (String friendID : friendIDs) {
			
			friendIdsClone.add(friendID);
		
		}
		
		friendIdsClone.retainAll(volunteerFriends.keySet());
		List<FBFriend> commonFriends = new ArrayList<FBFriend>();
		for (String friendID : friendIdsClone) {
			commonFriends.add(myFriends.get(friendID));
			
		}
		return commonFriends;
	}

	private void dontApproveVolunteer(final String volunteerId,final UserRequest request, final FlexTable fxTableVolunteers,final int row) {
		// first we update the request
		request.setStatus(walkieStatus.NEW);
		request.setApprovedWalkerID(null);
		WalkieDoggie.requestService.UpdateRequest(request, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				//after the request was updated, we update the credits of the volunteer
				updateCreditPoints(volunteerId,request,fxTableVolunteers,row, -2);				
			}
			
			@Override
			public void onFailure(Throwable caught) {

				WalkieDoggie.handleError(caught);

			}
		});

	}

	private void approveVolunteer(final String volunteerId, final UserRequest request, final FlexTable fxTableVolunteers, final int row) {
		// first we update the request
		request.setStatus(walkieStatus.APPROVED);
		request.setApprovedWalkerID(volunteerId);
		WalkieDoggie.requestService.UpdateRequest(request, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				//after the request was updated, we update the credits of the volunteer
				updateCreditPoints(volunteerId,request,fxTableVolunteers,row, +2);				
			}

			@Override
			public void onFailure(Throwable caught) {

				WalkieDoggie.handleError(caught);

			}
		});

	}

	private void updateCreditPoints(final String volunteerId,UserRequest request, final FlexTable fxTableVolunteers, final int row, int delta) {
		//temporary by nickname. it will be changed to be the user id 
		WalkieDoggie.usersService.setCredits(volunteerId,delta, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				
				loadMyWalkies();
				
			}

			@Override
			public void onFailure(Throwable caught) {
				WalkieDoggie.handleError(caught);

			}
		});


	}

	public void addRequestDisplay(final UserRequest request){

		requests.add(request);
		displayMyWalkies(requests);
		//this.displayMyWalkie(request);
		emptyLabel.setText("");

	}

	public ArrayList<UserRequest> getRequests() {
		return requests;
	}

	private String[] getIds(FBFriend[] friends) {

		if (friends==null)
			return null;
		String[] res = new String[friends.length];

		for (int i=0 ; i<res.length ; i++){
			res[i] = friends[i].getId();
		}

		return res;
	}


}